<#include "api_header.ftl">
<h3><strong>1 请求模型</strong></h3>
<h4><strong>1.1请求模型直接借鉴TOP的思想</strong></h4>
<p>请求模型直接借鉴TOP的思想，开放平台的所有服务URL是相同的。请求参数分为系统级参数和业务级参数两部分，系统级参数是所有服务API都拥有的参数，而业务级参数由具体服务API定义。</p>
<h4><strong>1.2系统级参数</strong></h4>
<p>系统级参数是由开放平台定义的一组参数，每个服务都拥有这些参数，用以传送框架级的参数信息。共有7个系统级参数，如下：</p>
	<table class="table table-striped" border="1" >
	          <thead>
	            <tr>
	            
	              <th>参数名称</th>
	              <th>必须</th>
	              <th>参数说明</th>
	            </tr>
	          </thead>
	          <tbody>


	            <tr>
	               <td>appcode</td>
	              <td>是</td>
	              <td>应用编码，用以确定客户端应用的身份。一个应用编码对应一个密钥。</td>
	            </tr>
	            
	             <tr>
	               <td>session</td>
	              <td>否</td>
	              <td>会话令牌，一般是一个36位的UUID，在登录服务平台后获取。</td>
	            </tr>
	            
	             <tr>
	               <td>method</td>
	              <td>是</td>
	              <td>服务方法名，一般采用“名词+动词”的结构定义。</td>
	            </tr>
	            
	             <tr>
	               <td>v</td>
	              <td>是</td>
	              <td>服务方法的版本号，如1.0、2.0等。一个具体的服务方法上method+v两者唯一确定。因此服务平台必须保证所有服务的method+v的唯一性。</td>
	            </tr>
	            
	             <tr>
	               <td>format</td>
	              <td>否</td>
	              <td>通信报文格式，可选值为xml和json，默认为xml。</td>
	            </tr>
	            
	             <tr>
	               <td>locale</td>
	              <td>否</td>
	              <td>本地化类型，默认为zh_CN</td>
	            </tr>
	            
	             <tr>
	               <td>sign</td>
	              <td>否</td>
	              <td>签名串，请求参数的签名，服务平台通过它验证请求数据的合法性。</td>
	            </tr>


	          </tbody>
	        </table>
	        
<h4><strong> 1.3 业务级参数</strong></h4>
<p>业务级参数，顾名思义是由业务逻辑需要自行定义的，每个服务API都可以定义若干个自己的业务级参数。</p>
<h4><strong>1.4 应用编码/应用密钥</strong></h4>
<p>服务开放平台通过一个应用申请流程，向通过审核的开发者分配一个唯一的应用编码/应用密钥（即appCode/appSecret）。应用编码是公开的，而应用密钥是保密的，只有开发者自己知道。</P>
<p>开发者开发的应用在访问开放平台的服务时，都必须带上这个应用编码，以亮明自己的身份。此外，还必须通过应用密钥对请求数据进行签名，
 开放平台通过验证服务请求的签名判断客户端应用的合法性。也就是说，开放平台通过应用编码/应用密钥的机制对应用进行身份认证。要基于服务平台开发应用，开发者必须事先通过申请获取应用编码/应用密钥后，才能进行应用的开发。</p> 
<h3><strong>2  签名算法</strong></h3>
 <p> 签名算法直接参考TOP的签名算法，该签名算法描述如下：</p>
 <p>(1) 所有请求参数按参数名升序排序；</p>
 <p>(2) 按请求参数名及参数值相互连接组成一个字符串：<paramName1><paramValue1><paramName2><paramValue2>…；</p>
 <p>(3) 将应用密钥分别添加到以上请求参数串的头部和尾部：<secret><请求参数字符串><secret>；</p>
 <p>(4) 对该字符串进行SHA1运算，得到一个二进制数组；</p>
 <p>(5) 将该二进制数组转换为十六进制的字符串，该字符串即是这些请求参数对应的签名；</p>
 <p>(6) 该签名值使用sign系统级参数一起和其它请求参数一起发送给服务开放平台。</p>
 <p>假设，user.create的服务有3个业务级参数，分别为name、age及sex。这些业务级参数和系统级参数的值如下表所示：</p>
 
 <table class="table table-striped" border="1">
	          <thead>
	            <tr>
	            
	              <th>系统级参数名称</th>
	              <th>参数值</th>
	              <th>业务级参数名称</th>
	              <th>参数值</th>
	            </tr>
	          </thead>
	          <tbody>


	            <tr>
	              <td>appcode</td>
	              <td>000001</td>
	              <td>name</td>
	              <td>tom</td>
	            </tr>
	            
	             <tr>
	              <td>session</td>
	              <td>AAAA</td>
	              <td>age</td>
	              <td>24</td>
	            </tr>
	            
	            <tr>
	              <td>method</td>
	              <td>user.create</td>
	              <td>sex</td>
	              <td>1</td>
	            </tr>
	            
	             <tr>
	              <td>locale</td>
	              <td>zh_CN</td>
	              <td></td>
	              <td></td>
	            </tr>
	            
	             <tr>
	              <td>v</td>
	              <td>1.0</td>
	              <td></td>
	              <td></td>
	            </tr>
	            
	            
	             <tr>
	              <td>format</td>
	              <td>xml</td>
	              <td></td>
	              <td></td>
	            </tr>
	           
	          </tbody>
	        </table>

		
		
<p>根据算法，首先按字母顺序将所有参数名和参数值拼装成一个字符串：</p>
<p><font color="#FF00FF">age24appcode00001formatjsonlocalezh_CNmethoduser.createnametomsessionAAAAsex1v1.0</font></p>
<p>假设，appCode为000001的appSecret是“abcdef”，则将“abcdef”分别添加到以上请求参数串的头部和尾部，得到：</p>
<p><font color="#FF00FF">abcdefage24appcode00001formatjsonlocalezh_CNmethoduser.createnametomsessionAAAAsex1v1.0abcdef</font></p>
<p>对以上字符串进行SHA1签名运算，将签名值转换为十六进制的编码串，得到：</p>
<p><font color="#FF00FF">5F1A5F00DA133B37CAC95E4FCAB71FA477A870CE</font></p>
<p>最后，客户端即可使用如下的URL请求串对user.create服务方法发起请求：</p>
<p><font color="#FF00FF">http://<serverUrl>/<ropServletUri>?appcode=000001&method=user.create&…&sign=5F1A5F00DA133B37CAC95E4FCAB71FA477A870CE</font></p>


<h3><strong>3 通讯方式</strong></h3>
<p><strong>协议:</strong>	HTTP <p>
<p><strong>方法:</strong>	GET/POST<p>

<h3><strong>4.错误模型</strong></h3>



<p>平台参考TOP建立了一个完整的错误模型，该错误模型拥有强大的表达能力和扩展性，很多错误自动于R平台负责处理，对于业务性的错误，开发者按错误模型构造即可。</p>
<p>平台的错误模型分为主错误和子错误两个层级，每个错误报文都会对应一个主错误和干个子错误，主错误描述错误的类型，子错误说明错误的原因。子错误根据责任归属可以划
分为ISP(Internet Service Provider)和ISV(Independent Software Vendors)两种类型的错误</p>
<p>ISP代表平台服务提供商一方，如服务内部异常、服务端数据库资源不可用等错误，其>责任归属于ISP，这类错误称为ISP错误。ISP错误的错误编码以“isp.”为前缀，如isp.xxx-service-unavailable、isp.xxx-service-timeout等。
ISV代表基于平台服务开发应用的开发者一方，这类错误产生的原因是由开发者造成的。ISV错误的错误编码以“isv.”为前缀，如isv.invalid-permission、isv.missing-parameter:xxx等。</p>
<p>当服务发生错误时，Rop将返回统一格式的错误报文，它由一个主错误和若干个子错误组成。</p>
<h4><strong>4.1系统级主错误编码</strong></h4>
<p>平台内置定义了一套和业务无关的错误代码体系，称这些错误为系统级错误。平台在i18n/rop/error的国际化资源文件中定义了系统级主错误及子错误。</P>
<p>在平台中，主错误都对应一个唯一数字编码，目前共包括27个主错误，如下：</p>

<table class="table table-striped" border="1">
	          <thead>
	            <tr>
	            
	              <th>编码</th>
	              <th>错误说明</th>
	              <th>编码</th>
	              <th>错误说明</th>
	              <th>编码</th>
	              <th>错误说明</th>
	            </tr>
	          </thead>
	          <tbody>


	            <tr>
	              <td>1</td>
	              <td>服务不可用</td>
	              <td>20</td>
	              <td>缺少session参数</td>
	              <td>29</td>
	              <td>非法的版本参数</td>
	            </tr>
	            
	             <tr>
	              <td>2</td>
	              <td>开发者权限不足</td>
	              <td>21</td>
	              <td>无效的session参数</td>
	              <td>30</td>
	              <td>不支持的版本号</td>
	            </tr>
	            
	             <tr>
	              <td>3</td>
	              <td>用户权限不足</td>
	              <td>22</td>
	              <td>缺少appcode参数</td>
	              <td>31</td>
	              <td>无效报文格式类型</td>
	            </tr>
	            
	             <tr>
	              <td>4</td>
	              <td>图片上传失败</td>
	              <td>23</td>
	              <td>无效的appcode参数</td>
	              <td>32</td>
	              <td>缺少必选参数</td>
	            </tr>
	            
	            
	            <tr>
	              <td>5</td>
	              <td>HTTP方法被禁止</td>
	              <td>24</td>
	              <td>缺少签名参数</td>
	              <td>33</td>
	              <td>非法的参数</td>
	            </tr>
	            
	            
	            <tr>
	              <td>6</td>
	              <td>编码错误</td>
	              <td>25</td>
	              <td>无效签名</td>
	              <td>34</td>
	              <td>用户调用服务的次数超限</td>
	            </tr>
	            
	            <tr>
	              <td>7</td>
	              <td>请求被禁止</td>
	              <td>26</td>
	              <td>缺少方法名参数</td>
	              <td>35</td>
	              <td>会话调用服务的次数超限</td>
	            </tr>
	            
	            <tr>
	              <td>8</td>
	              <td>服务已经作废</td>
	              <td>27</td>
	              <td>不存在的方法名</td>
	              <td>36</td>
	              <td>应用调用服务的次数超限</td>
	            </tr>
	            
	            <tr>
	              <td>9</td>
	              <td>业务逻辑出错</td>
	              <td>28</td>
	              <td>缺少版本参数</td>
	              <td>37</td>
	              <td>应用调用服务的频率超限</td>
	            </tr>
	            
	            <tr>
	              <td>38</td>
	              <td>对象不存在</td>
	              <td></td>
	              <td></td>
	              <td></td>
	              <td></td>
	            </tr>
	            
	            
	           
	          </tbody>
	        </table>

<p>27个系统级错误可以划分为以下几类：</P>
<p><strong>系统级参数错误：</strong>这类错误是由于系统级请求参数缺失或不合法引起的，20~31都是这一类型的错误;</p>
<p><strong>业务级参数错误：</strong>业务级参数缺失或不合法而引起的错误，如32和33；</p>
<p><strong>服务访问超限错误：</strong>客户端的服务调用超过配额，34~37都是这一类型的错误；</p>
<p><strong>权限不足错误：</strong>如2和3的错误都是开发者或应用用户的权限不足，造成服务无法访问的错误；</p>
<p><strong>其它错误：</strong>以上类型之外的错误。</p>
<p></p>
<h4><strong>4.2系统级子错误编码</strong></h4>
<p></p>
<p><strong><font color="#FF00FF">ISP子错误编码</font></strong></P>
<p>平台目前仅拥有两个ISP的子错误，它们对应的主错误编码为1，即ServiceCurrentlyUnavailable主错误。这两个ISP子错误分别是：</p>
<p>isp.xxx-service-unavailable=调用后端服务{0}抛异常:{1}，服务不可用。异常信息:{2}</p>
<p>isp.xxx-service-timeout=调用{0}服务超时，该服务的超时限制为{1}秒，请和服务平台提供商联系</p>
<p></p>
<p>因服务平台原因产生的任何错误，如数据库连接不上，某个服务资源不可用，内部抛出异常等，都对应isp.xxx-service-unavailable的ISP子错误。其中子错误代码中的xxx会被替换成具体的服务名。
如user.get服务对应的子错误码为：isp.user-get-service-unavailable。isp.xxx-service-unavailable的错误消息是带参数的格式化串，Rop会将引起错误的异常信息格式化到消息内容中。</p>
<p>平台允许设置服务执行的最大过期时间，即一个服务的执行超过指定限时后，直接返回错误报文，释放服务端资源，以平衡服务平台资源的利用。平台默认不设置服务过期时间，
可通过<rop:annotation-driven/>的service-timeout-seconds属性指定服务执行最大过期时间，单位为秒。每个服务方法都可以定义自己的服务过期时间，以覆盖<rop:annotation-driven/>所定义的统一过期时间。</p>
<p></p>
<p><strong><font color="#FF00FF">ISV子错误编码</font></strong></p>
<p></p>
<p>在实际应用中，开发者遇到更多的都会是ISV的错误。平台定义了5个ISV子错误，说明如下：</p>
<p>isv.missing-parameter:xxx=缺少必要的参数{0}</p>
<p>isv.parameters-mismatch:xxx-and-yyy=传入的参数{0}和{1}不匹配；</p>
<p>isv.invalid-paramete:xxx=参数{0}无效，格式不对、非法值、越界等</p>
<p>isv.invalid-permission=权限不够、非法访问</p>
<p>isv.xxx-not-exist:invalid-yyy=根据{0}查询不到{1}</p>		

			
			
			
			
<#include "api_footer.ftl">
